﻿using AnesSystem.Controls;
using AnesSystem.Models;
using AnesSystem.Util;
using AnesSystem.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Threading;

namespace AnesSystem.Services
{
    public class VitalSignCapture : BaseViewModel<VitalSignCapture>
    {
        #region Variables
        private static DateTime _lastReadTime;

        private System.Threading.Timer timer;

        private int delay;

        private int flag;

        private bool isStart;




        #endregion


        #region Constructor

        public VitalSignCapture()
        {
        }
        #endregion


        #region Properties
        public DateTime LastReadTime
        {
            get
            {
                return _lastReadTime;
            }

            set
            {
                _lastReadTime = value;
            }
        }
        public PatientLinkModel CurPatientLink
        {
            get
            {
                return DataManager.Instance.CurrentPatientLink == null ? null : DataManager.Instance.CurrentPatientLink;
            }
        }

        #endregion


        #region 依赖属性


        #endregion


        #region Event

        public event EventHandler<CaptureVitalArgs> VitalSignCaptured;

        #endregion


        #region PrivateMethods
        /// <summary>
        /// 采集数据
        /// </summary>
        private void ReadDeviceCapture(bool isFirst)
        {
            Common.LogHelper.Info(this.GetType(), DateTime.Now.ToString(DateFormat.DATE_FORMAT_STR_YMDHMS) + "ReadDeviceCapture Running···");
            Console.WriteLine(DateTime.Now.ToString(DateFormat.DATE_FORMAT_STR_YMDHMS) + "ReadDeviceCapture Running···");
            if (OperationDataPool.Instance.CurOperationData == null)
            {
                return;
            }
            DateTime inRoomTime = DataManager.Instance.CurrentPatientLink.Status.InRoomTime;
            DateTime startTime = CalStartTime(inRoomTime);
            DateTime curTime = DateTime.Now;
            if (LastReadTime.Equals(new DateTime()))
            {
                DateTime outRoomTime = DataManager.Instance.CurrentPatientLink.Status.OutRoomTime;
                if (!outRoomTime.Equals(new DateTime()))
                {
                    LastReadTime = outRoomTime.AddMinutes(1);
                }
                else
                {
                    LastReadTime = inRoomTime;
                }
            }
            List<VitalSignCacheModel> list = VitalSignCacheService.Instance.FindRangeSigns(DataManager.Instance.CurRoom.Name, LastReadTime, DateTime.Now);
            Dictionary<string, Dictionary<DateTime, VitalSignCacheModel>> mapCode2Time = new Dictionary<string, Dictionary<DateTime, VitalSignCacheModel>>();
            //索引
            foreach (var item in list)
            {
                if (!mapCode2Time.ContainsKey(item.code))
                {
                    mapCode2Time.Add(item.code, new Dictionary<DateTime, VitalSignCacheModel>());
                }

                Dictionary<DateTime, VitalSignCacheModel> dic = mapCode2Time[item.code];
                if (!dic.ContainsKey(item.captureTime))
                {
                    dic.Add(item.captureTime, item);
                }
            }

            Dictionary<int, List<ConfigVitalSignsModel>> mapPeriod = DataManager.Instance.PeriodTime2signs;
            DateTime maxReadTime = new DateTime();
            foreach (var period in mapPeriod.Keys.ToList())
            {
                List<ConfigVitalSignsModel> signList = mapPeriod[period];
                foreach (var sign in signList)
                {
                    if (!mapCode2Time.ContainsKey(sign.code))
                    {
                        continue;
                    }
                    Dictionary<DateTime, VitalSignCacheModel> timeMap = mapCode2Time[sign.code];
                    DateTime time = startTime;

                    while (time.CompareTo(curTime) <= 0)
                    {
                        //入室之前的参数不要.修改了入室时间，需要重新计算
                        DateTime maxTime = GetMaxTime(inRoomTime, LastReadTime);
                        if (!(time.CompareTo(maxTime) < 0))
                        {
                            VitalSignCacheModel Vsm = FindDeviceCap(timeMap, time, period, inRoomTime);
                            if (Vsm != null)
                            {
                                if (IsEmpty(Vsm.code, time))
                                {
                                    PatientVitalSignsModel pvm = CopyDeviceData(Vsm);
                                    if (pvm != null)
                                    {
                                        pvm.PatientID = DataManager.Instance.CurrentPatientLink.Id.ToString();
                                        pvm.CaptureTime = time;
                                        //第一次进入麻醉单，缓存还没加载，直接存入数据库
                                        if (isFirst)
                                        {
                                            PatientVitalSignsServicie.Instance.AddUpdate(pvm);
                                        }
                                        else
                                        {
                                            VitalSignCaptured?.Invoke(this, new CaptureVitalArgs(pvm));
                                        }
                                       

                                    }
                                }
                            }
                        }
                        time = time.AddMilliseconds(period * 1000);
                    }
                    time = time.AddMilliseconds(-period * 1000);
                    if (maxReadTime.Equals(new DateTime()))
                    {
                        maxReadTime = time;
                    }
                    maxReadTime = GetMinTime(time, maxReadTime);
                }
            }
            if (maxReadTime.Equals(new DateTime()))
            {
                LastReadTime = new DateTime();
            }
            else
            {
                LastReadTime = maxReadTime;
            }

        }



        /// <summary>
        /// 转换体征数据
        /// </summary>
        /// <param name="vsm"></param>
        /// <returns></returns>
        private PatientVitalSignsModel CopyDeviceData(VitalSignCacheModel vsm)
        {
            if (("param_T").Equals(vsm.code))
            {
                if (double.Parse(vsm.modValue) < 34)
                {
                    Common.LogHelper.Info(this.GetType(), "Anes capturing data，but is not display, the data Code: " + vsm.code + "-- value：" + vsm.modValue);
                    return null;
                }
            }
            PatientVitalSignsModel pvm = new PatientVitalSignsModel();
            pvm.Code = vsm.code;
            pvm.CaptureTime = vsm.captureTime;
            pvm.Scale = vsm.scale;
            pvm.ModValue = vsm.modValue;
            pvm.Name = vsm.name;
            pvm.DataType = 0;
            pvm.UnitName = vsm.unitName;
            pvm.InitValue = vsm.initValue;
            return pvm;
        }



        /// <summary>
        /// 判断是否存在(人为删除视为存在)
        /// </summary>
        /// <param name="code"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        private bool IsEmpty(string code, DateTime time)
        {
            string pid = DataManager.Instance.CurrentPatientLink.Id.ToString();
            PatientVitalSignsModel pvm = PatientVitalSignsServicie.Instance.GetVitalSign(pid, code, time);
            if (pvm != null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 小时的起始时间，分钟为零
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        private DateTime CalStartTime(DateTime date)
        {
            return date.AddMinutes(-date.Minute).AddSeconds(-date.Second).AddMilliseconds(-date.Millisecond);
        }
        /// <summary>
        /// 取最大时间
        /// </summary>
        /// <param name="time1"></param>
        /// <param name="time2"></param>
        /// <returns></returns>
        private DateTime GetMaxTime(DateTime time1, DateTime time2)
        {
            if (time1.CompareTo(time2) == 0)
            {
                return time1;
            }
            else
            {
                if (time1.CompareTo(time2) > 0)
                {
                    return time1;
                }
                else
                {
                    return time2;
                }
            }
        }
        /// <summary>
        /// 去最小时间
        /// </summary>
        /// <param name="time1"></param>
        /// <param name="time2"></param>
        /// <returns></returns>
        private DateTime GetMinTime(DateTime time1, DateTime time2)
        {
            if (time1.CompareTo(time2) == 0)
            {
                return time1;
            }
            else
            {
                if (time1.CompareTo(time2) > 0)
                {
                    return time2;
                }
                else
                {
                    return time1;
                }
            }
        }

        /// <summary>
        /// 取采集数据
        /// </summary>
        /// <param name="timeMap"></param>
        /// <param name="endTime"></param>
        /// <param name="period"></param>
        /// <param name="inRoomTime"></param>
        /// <returns></returns>
        private VitalSignCacheModel FindDeviceCap(Dictionary<DateTime, VitalSignCacheModel> timeMap, DateTime endTime, int period, DateTime inRoomTime)
        {
            VitalSignCacheModel vitalSignCacheModel = null;
            if (timeMap.ContainsKey(endTime))
            {
                vitalSignCacheModel = timeMap[endTime];
            }

            if (vitalSignCacheModel != null)
            {
                return vitalSignCacheModel;
            }
            else
            {
                DateTime t1 = endTime.AddMilliseconds(-period * 1000);
                if (t1.CompareTo(inRoomTime) < 0)
                {
                    t1 = inRoomTime;
                }
                DateTime t2 = endTime.AddMilliseconds(-60 * 1000);
                //一分钟一分钟往回找
                while (t2.CompareTo(t1) > 0)
                {

                    if (timeMap.ContainsKey(t2))
                    {
                        vitalSignCacheModel = timeMap[t2];
                    }
                    else
                    {
                        vitalSignCacheModel = null;
                    }
                    if (vitalSignCacheModel != null)
                    {
                        return vitalSignCacheModel;
                    }
                    t2 = t2.AddMilliseconds(-60 * 1000);
                }
            }
            return vitalSignCacheModel;

        }
        /// <summary>
        /// 刷新页数
        /// </summary>
        private void IsAddPage()
        {
            if (OperationDataPool.Instance.CurOperationData == null || DataManager.Instance.CurrentPatientLink == null)
            {
                return;
            }
            if (DataManager.Instance.CurrentPatientLink.Status.InPacuTime.Equals(new DateTime()))
            {
                int totalPage = DataManager.Instance.CurrentPatientLink.Status.TotalPage;
                DateTime anesStartTime = DataManager.Instance.CurrentPatientLink.Status.AnesRecordStartTime;
                TimeSpan span = DateTime.Now - anesStartTime;
                int millSeconds = (int)span.TotalMilliseconds;
                if (millSeconds > totalPage * 4 * 60 * 60 * 1000)
                {
                    DataManager.Instance.CurrentPatientLink.Status.TotalPage = totalPage + 1;
                    PatientLinkService.Instance.AddUpdate(DataManager.Instance.CurrentPatientLink);
                    DataManager.Instance.TableHeaderCtrl._anesProcessCtrl.ViewModel.ChangeTotalPage();
                    Console.WriteLine("the anesTotalPage is add 1!");
                    Common.LogHelper.Info(this.GetType(), "the anesTotalPage is add 1!");
                }
            }
            else
            {
                int totalPage = DataManager.Instance.CurrentPatientLink.Status.PacuPage;
                DateTime pacuStartTime = DataManager.Instance.CurrentPatientLink.Status.PacuStartTime;
                TimeSpan span = DateTime.Now - pacuStartTime;
                int millSeconds = (int)span.TotalMilliseconds;
                if (millSeconds > totalPage * 4 * 60 * 60 * 1000)
                {
                    DataManager.Instance.CurrentPatientLink.Status.PacuPage = totalPage + 1;
                    PatientLinkService.Instance.AddUpdate(DataManager.Instance.CurrentPatientLink);
                    PacuProcessViewModel.Instance.ChangeTotalPage();
                    Console.WriteLine("the pacuTotalPage is add 1!");
                    Common.LogHelper.Info(this.GetType(), "the pacuTotalPage is add 1!");
                }
            }

        }
        #endregion


        #region Public/ProtectedMethods

        public void StartCapture()
        {
            if (isStart)
            {
                return;
            }
            StopCapture();
            ReadDeviceCapture(true);
            LastReadTime = new DateTime();
            DateTime date = DateTime.Now;
            delay = 300 - (date.Minute % 5 * 60 + date.Second);
            Console.WriteLine("the delay:" + delay);
            timer = new System.Threading.Timer(Timer_Tick, null, delay * 1000, 5 * 60 * 1000);
            isStart = true;
            // StartTask();
            //模拟采集器
 //           StartTask2();



        }

        private void Timer_Tick(object state)
        {

            SynchronizationContext.SetSynchronizationContext(new
              DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
            SynchronizationContext.Current.Post(pl =>
            {
                IsAddPage();
            }, null);

            ReadDeviceCapture(false);
        }


        private void StartTask2()
        {
            Task.Factory.StartNew(delegate
            {
                while (true)
                {
                    DateTime date = DateTime.Now;
                    VitalSignCacheModel vsm = new VitalSignCacheModel();
                    vsm.roomNo = "5";
                    vsm.code = "param_resp";
                    vsm.name = "呼吸";
                    vsm.initValue = "25";
                    vsm.modValue = "25";
                    vsm.dataType = 0;
                    vsm.scale = 0;
                    vsm.unitName = "mmhg";
                    vsm.captureTime = date.AddSeconds(-date.Second).AddMilliseconds(-date.Millisecond);
                    Console.WriteLine("正在存储数据" + date.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm);

                    DateTime date1 = DateTime.Now;
                    VitalSignCacheModel vsm1 = new VitalSignCacheModel();
                    vsm1.roomNo = "5";
                    vsm1.code = "param_resp_ctrl";
                    vsm1.name = "控制呼吸";
                    vsm1.initValue = "25";
                    vsm1.modValue = "30";
                    vsm1.dataType = 0;
                    vsm1.scale = 0;
                    vsm1.unitName = "mmhg";
                    vsm1.captureTime = date1.AddSeconds(-date1.Second).AddMilliseconds(-date1.Millisecond);
                    Console.WriteLine("正在存储数据" + date1.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm1);

                    DateTime date2 = DateTime.Now;
                    VitalSignCacheModel vsm2 = new VitalSignCacheModel();
                    vsm2.roomNo = "5";
                    vsm2.code = "param_spo2";
                    vsm2.name = "血氧饱和度";
                    vsm2.initValue = "99";
                    vsm2.modValue = "99";
                    vsm2.dataType = 0;
                    vsm2.scale = 0;
                    vsm2.unitName = "mmhg";
                    vsm2.captureTime = date2.AddSeconds(-date2.Second).AddMilliseconds(-date2.Millisecond);
                    Console.WriteLine("正在存储数据" + date2.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm2);

                    DateTime date3 = DateTime.Now;
                    VitalSignCacheModel vsm3 = new VitalSignCacheModel();
                    vsm3.roomNo = "5";
                    vsm3.code = Constants.PARAM_NIBP_S;
                    vsm3.name = "无创收缩压";
                    vsm3.initValue = "70";
                    vsm3.modValue = "70";
                    vsm3.dataType = 0;
                    vsm3.scale = 0;
                    vsm3.unitName = "mmhg";
                    vsm3.captureTime = date3.AddSeconds(-date3.Second).AddMilliseconds(-date3.Millisecond);
                    Console.WriteLine("正在存储数据" + date3.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm3);

                    DateTime date4 = DateTime.Now;
                    VitalSignCacheModel vsm4 = new VitalSignCacheModel();
                    vsm4.roomNo = "5";
                    vsm4.code = Constants.PARAM_NIBP_D;
                    vsm4.name = "无创舒张压";
                    vsm4.initValue = "120";
                    vsm4.modValue = "120";
                    vsm4.dataType = 0;
                    vsm4.scale = 0;
                    vsm4.unitName = "mmhg";
                    vsm4.captureTime = date4.AddSeconds(-date4.Second).AddMilliseconds(-date4.Millisecond);
                    Console.WriteLine("正在存储数据" + date4.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm4);

                    DateTime date5 = DateTime.Now;
                    VitalSignCacheModel vsm5 = new VitalSignCacheModel();
                    vsm5.roomNo = "5";
                    vsm5.code = "param_T";
                    vsm5.name = "体温";
                    vsm5.initValue = "33.3";
                    vsm5.modValue = "33.3";
                    vsm5.dataType = 0;
                    vsm5.scale = 0;
                    vsm5.unitName = "mmhg";
                    vsm5.captureTime = date5.AddSeconds(-date5.Second).AddMilliseconds(-date5.Millisecond);
                    Console.WriteLine("正在存储数据" + date5.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm5);

                    DateTime date6 = DateTime.Now;
                    VitalSignCacheModel vsm6 = new VitalSignCacheModel();
                    vsm6.roomNo = "5";
                    vsm6.code = Constants.PARAM_IBP_D;
                    vsm6.name = "有创舒张压";
                    vsm6.initValue = "140";
                    vsm6.modValue = "140";
                    vsm6.dataType = 0;
                    vsm6.scale = 0;
                    vsm6.unitName = "mmhg";
                    vsm6.captureTime = date6.AddSeconds(-date6.Second).AddMilliseconds(-date6.Millisecond);
                    Console.WriteLine("正在存储数据" + date6.ToString(DateFormat.DATE_FORMAT_STR_YMDHM));
                    VitalSignCacheModelService.Instance.AddUpdate(vsm6);
                    Thread.Sleep(10 * 1000);
                }

            });
        }

        private void StartTask()
        {


            //Task.Factory.StartNew(delegate
            //{
            //    while (true) {
            //        if (!isStart)
            //            Thread.Sleep(10 * 1000);
            //        isStart = true;
            //        ReadDeviceCapture();
            //        Thread.Sleep(60 * 1 * 1000);
            //    }

            //});
        }
        //static bool isCapture = false;
        //private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        //{
        //    flag++;
        //    Console.WriteLine(DateTime.Now.ToString(DateFormat.DATE_FORMAT_STR_YMDHMS) + "Timer Started··· this.Interval" + timer.Interval);
        //    if (flag >= delay)
        //    {
        //        isCapture = true;
        //        StopCapture();
        //        timer.Interval = 5 * 60 * 1000;
        //        timer.Start();
        //        IsAddPage();
        //        ReadDeviceCapture();
        //        Console.WriteLine(DateTime.Now.ToString(DateFormat.DATE_FORMAT_STR_YMDHMS) + "Timer Started··· this.Interval" + timer.Interval);
        //    }
        //}

        public void StopCapture()
        {
            if (timer != null)
            {
                Console.WriteLine("the capture is closed!");
                Common.LogHelper.Info(this.GetType(), "the capture is closed!");
                timer.Change(-1, 5);
                isStart = false;
            }

        }
        #endregion


        #region EventHandlers


        #endregion
    }
}
